#include "stm32f10x.h"                  // Device header
#include "LED.h"
#include <stdio.h>

uint8_t Serial_RxData;
char RxDataPacket[100];
uint8_t RxFlag;


/*
@brief: 串口初始化
@param: 无
@retval 无
*/
void Serial_Init(void)
{
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	// 初始化
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						//将PA9引脚初始化为TX
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						//将PA10引脚初始化为RX
	
	// 串口初始化
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
		
	// NVIC配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		
	NVIC_InitTypeDef NVIC_InitStructure;					
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		
	NVIC_Init(&NVIC_InitStructure);							

	// 打开串口外设
	USART_Cmd(USART1, ENABLE);
}

/*
@brief: 串口发送一个字节
@param: uint8_t 类型
@retval 无
*/
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

/*
@brief: 串口自定义幂函数
@param: 底数X, 幂指数Y, 取值范围是 0 - 255
@retval 无
*/
uint32_t Serial_Pow(uint8_t X, uint8_t Y)
{
	uint32_t result = 1;	// 注意数据类型
	while (Y > 0)
	{
		result *= X;
		Y --;
	}
	return result;
}

/*
@brief: 串口发送一个字符串
@param: 要发送的字符串的首地址
@retval 无
*/
void Serial_SendString(char *String)
{
	for (uint8_t i = 0; String[i] != '\0'; i++)
	{
		Serial_SendByte(String[i]);
	}
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
//	Serial_SendByte('\r');    	// 回车键
//	Serial_SendByte('\n');		// 换行符

}

/*
@brief: 串口发送一个数
@param_1: 要发送的数,u16类型, 取值范围是 0 - 65535
@param_2: 要发送的数的长度, uint8_t类型
@retval 无
*/
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

/*
@brief: 读取标志位函数
@param: 无
@retval 0/1
*/
//uint8_t Serial_GetRxFlag(void)
//{
//	if (RxFlag == 1)
//	{
//		RxFlag = 0;
//		return 1;
//	}
//	return 0;
//}

/*
@brief: 获取串口接收的数据(转存????)
@param: 无
@retval uint8_t 接收的数据
*/
uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}

/*
@brief: 重定向printf函数到串口(无需在头文件声明)
@param: int ch 要发送的字符
@retval int 要打印的数据
*/
int fputc(int ch, FILE *f)
{
	Serial_SendByte((uint8_t)ch);	// 将printf底层重新定向到自己的串口发送函数
	return ch;
}

/*
@brief: 提示操作指令
@param: 无
@retval 无
*/
void Show_Message(void)
{
	printf("Commands Like This List:\r\n");
	printf("@1111#  ----  LED1_ON\r\n");
	printf("@2222#  ----  LED2_ON\r\n");
	printf("@3333#  ----  ALL_LEDs_OFF\r\n");

}

void USART1_IRQHandler(void)
{
	static uint8_t Rxstate = 0;
	static uint8_t nRxPacket = 0;
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{	
//		LED2_ON();
		Serial_RxData = USART_ReceiveData(USART1);		// 收到数据
		if (Rxstate == 0)		// 处于状态0
		{
			if (Serial_RxData == '@' && RxFlag == 0)		// 如果收到包头
			{
				Rxstate = 1;		// 则进入下一个状态
				nRxPacket = 0;		// 把数据量 置0
			}
		}
		else if (Rxstate == 1)
		{
			if (Serial_RxData == '@')		// 如果第一个数据仍是包头@, 则重新进入状态1
			{
				Rxstate = 1;
			}
			else if (Serial_RxData == '#')  // 如果收到的数据含有包尾#
			{
				Rxstate = 2;				// 进入状态2
			}
			else if (Serial_RxData != '@' && Serial_RxData != '#')	// 数据既不是包头也不是包尾
			{
				RxDataPacket[nRxPacket] = Serial_RxData;		// 则存进Rx数据包中
				nRxPacket ++;		// 累计进行存储
			}
		}
		
		else if (Rxstate == 2)		// 进入状态2
		{
			Rxstate = 0;
			RxDataPacket[nRxPacket] = '\0';		// 在数据末尾加上 '\0'
			RxFlag = 1;				// 此时数据完整, 置可读
		}	
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);		// 清除中断挂起位	
//		LED2_OFF();
	}
}
